package com.supermarket.manage.provider.instock.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.supermarket.manage.common.constant.StockConstant;
import com.supermarket.manage.common.dto.PageBean;
import com.supermarket.manage.common.dto.home.request.HomeInitParams;
import com.supermarket.manage.common.dto.home.response.ProfitDataDto;
import com.supermarket.manage.common.dto.home.response.TopDto;
import com.supermarket.manage.common.dto.home.response.TrendDto;
import com.supermarket.manage.common.dto.prod.response.ProductDto;
import com.supermarket.manage.common.dto.stock.request.InstockPageParams;
import com.supermarket.manage.common.dto.stock.response.InProdDto;
import com.supermarket.manage.common.dto.stock.response.InstockDto;
import com.supermarket.manage.common.pojo.Instock;
import com.supermarket.manage.common.pojo.InstockProd;
import com.supermarket.manage.common.pojo.Product;
import com.supermarket.manage.common.utils.BigDecimalUtil;
import com.supermarket.manage.common.utils.TimeUtil;
import com.supermarket.manage.provider.api.instock.InstockService;
import com.supermarket.manage.provider.api.product.ProductService;
import com.supermarket.manage.provider.instock.mapper.InstockMapper;
import com.supermarket.manage.provider.instock.mapper.InstockProdMapper;
import com.supermarket.manage.provider.instock.mapper.SupplierMapper;
import com.supermarket.manage.provider.util.IDUtil;
import org.apache.dubbo.config.annotation.Reference;
import org.apache.dubbo.config.annotation.Service;
import org.springframework.beans.BeanUtils;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;

/**
 * @author Faxon
 * @version 1.0
 * @date 2020-03-14 18:41
 **/
@Service(version = "1.0.0")
public class InstockServiceImpl implements InstockService {

    @Resource
    private InstockMapper instockMapper;

    @Resource
    private InstockProdMapper instockProdMapper;

    @Resource
    private IDUtil idUtil;

    @Resource
    private SupplierMapper supplierMapper;

    @Reference(version = "1.0.0")
    private ProductService productService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean addInstock(Instock instock) {
        //添加单据
        if (instock.getType().equals(StockConstant.SALE)) {
            instock.setId(idUtil.getPurchaseInId());
        } else {
            instock.setId(idUtil.getReturnInId());
        }
        Date date = new Date();
        instock.setCreated(date);
        instock.setUpdated(date);
        instockMapper.insert(instock);
        //添加关联商品
        List<InstockProd> instockProds = instock.getInstockProds();
        instockProds.forEach(p -> {
            p.setIid(idUtil.getUUID());
            p.setInstockId(instock.getId());
            p.setPnumber(BigDecimalUtil.formatTwoPoint(p.getPnumber()));
            p.setSubtotal(BigDecimalUtil.formatTwoPoint(p.getSubtotal()));
        });
        instockProdMapper.insertList(instockProds);
        return Boolean.TRUE;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateInstock(Instock instock) {
        //更新单据
        instockMapper.updateById(instock);
        //删除原本关联商品
        QueryWrapper<InstockProd> wrapper = new QueryWrapper<>();
        wrapper.eq("instock_id", instock.getId());
        instockProdMapper.delete(wrapper);
        //添加关联商品
        List<InstockProd> instockProds = instock.getInstockProds();
        instockProds.forEach(p -> {
            p.setIid(idUtil.getUUID());
            p.setInstockId(instock.getId());
            p.setPnumber(BigDecimalUtil.formatTwoPoint(p.getPnumber()));
            p.setSubtotal(BigDecimalUtil.formatTwoPoint(p.getSubtotal()));
        });
        instockProdMapper.insertList(instockProds);
        return Boolean.TRUE;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean addInstockAndUpdateStockingNumber(Instock instock) {
        //添加单据
        if (instock.getType().equals(StockConstant.SALE)) {
            instock.setId(idUtil.getPurchaseInId());
        } else {
            instock.setId(idUtil.getReturnInId());
        }
        Date date = new Date();
        instock.setCreated(date);
        instock.setUpdated(date);
        instockMapper.insert(instock);
        //添加单据关联商品
        List<InstockProd> instockProds = instock.getInstockProds();
        List<Product> products = new ArrayList<>();
        instockProds.forEach(p -> {
            p.setIid(idUtil.getUUID());
            p.setInstockId(instock.getId());
            p.setPnumber(BigDecimalUtil.formatTwoPoint(p.getPnumber()));
            p.setSubtotal(BigDecimalUtil.formatTwoPoint(p.getSubtotal()));
            Product product = new Product();
            product.setPid(p.getPid());
            product.setStockNumber(p.getPnumber());
            products.add(product);
        });
        instockProdMapper.insertList(instockProds);
        //增加库存
        productService.addStockingNumber(products);
        return Boolean.TRUE;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateInstockAndUpdateStockingNumber(Instock instock) {
        //更新单据
        instockMapper.updateById(instock);
        //删除原本关联商品
        QueryWrapper<InstockProd> wrapper = new QueryWrapper<>();
        wrapper.eq("instock_id", instock.getId());
        instockProdMapper.delete(wrapper);
        //添加关联商品并增加库存
        List<InstockProd> instockProds = instock.getInstockProds();
        List<Product> products = new ArrayList<>();
        instockProds.forEach(p -> {
            p.setIid(idUtil.getUUID());
            p.setInstockId(instock.getId());
            p.setPnumber(BigDecimalUtil.formatTwoPoint(p.getPnumber()));
            p.setSubtotal(BigDecimalUtil.formatTwoPoint(p.getSubtotal()));
            Product product = new Product();
            product.setPid(p.getPid());
            product.setStockNumber(p.getPnumber());
            products.add(product);
        });
        instockProdMapper.insertList(instockProds);
        productService.addStockingNumber(products);
        return Boolean.TRUE;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean doneInstockById(Instock instock) {
        //修改关联商品库存
        QueryWrapper<InstockProd> wrapper = new QueryWrapper<>();
        wrapper.eq("instock_id", instock.getId());
        List<InstockProd> prodList = instockProdMapper.selectList(wrapper);
        List<Product> products = new ArrayList<>();
        prodList.forEach(p -> {
            Product product = new Product();
            product.setPid(p.getPid());
            product.setStockNumber(p.getPnumber());
            products.add(product);
        });
        productService.addStockingNumber(products);
        //修改入库单状态
        instock.setUpdated(new Date());
        return instockMapper.updateById(instock) == 1;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteInstockById(String id) {
        QueryWrapper<InstockProd> wrapper = new QueryWrapper<>();
        wrapper.eq("instock_id", id);
        instockProdMapper.delete(wrapper);
        instockMapper.deleteById(id);
        return Boolean.TRUE;
    }

    @Override
    public PageBean<Instock> getInstockPageList(InstockPageParams params) {
        PageHelper.startPage(params.getPage(), params.getSize());
        Page<Instock> page = instockMapper.getInstockPageList(params);
        if (page == null) {
            return null;
        }
        return new PageBean<>(page.getPageNum(), page.getPageSize(), page.getResult(), page.getTotal());
    }

    @Override
    public InstockDto getInstockById(String id) {
        Instock instock = instockMapper.getInstockById(id);
        if (instock == null) {
            return null;
        }
        InstockDto dto = new InstockDto();
        BeanUtils.copyProperties(instock, dto);
        //查询入库商品信息
        QueryWrapper<InstockProd> wrapper = new QueryWrapper<>();
        wrapper.eq("instock_id", id);
        List<InstockProd> instockProds = instockProdMapper.selectList(wrapper);
        //将查询结果封装到map中
        Map<String, InProdDto> map = new HashMap<>(instockProds.size());
        List<String> ids = new ArrayList<>();
        instockProds.forEach(i -> {
            ids.add(i.getPid());
            InProdDto inProdDto = new InProdDto();
            inProdDto.setIid(i.getIid());
            inProdDto.setInstockId(id);
            inProdDto.setPid(i.getPid());
            inProdDto.setPnumber(i.getPnumber());
            inProdDto.setSubtotal(i.getSubtotal());
            inProdDto.setGray(Boolean.FALSE);
            map.put(i.getPid(), inProdDto);
        });
        //获取商品详情
        List<ProductDto> prods = productService.getProdDtoByPids(ids);
        List<InProdDto> data = new ArrayList<>();
        prods.forEach(p -> {
            InProdDto inProdDto = map.get(p.getPid());
            if (inProdDto != null) {
                inProdDto.setPname(p.getPname());
                inProdDto.setUnitName(p.getUnitName());
                inProdDto.setPic(p.getPic());
                inProdDto.setCostPrice(p.getCostPrice());
                inProdDto.setFirstCname(p.getFirstCname());
                inProdDto.setSecondCname(p.getSecondCname());
                inProdDto.setThirdCname(p.getThirdCname());
            }
            data.add(inProdDto);
        });
        dto.setInstockProds(data);
        return dto;
    }

    @Override
    public ProfitDataDto getPurchases(HomeInitParams params) {
        List<TopDto<Integer>> purchases = instockMapper.getPurchases(params);
        ProfitDataDto dataDto = new ProfitDataDto();
        BigDecimal zero = new BigDecimal("0.00");
        dataDto.setPurchases(zero);
        dataDto.setSalesBack(zero);
        if (purchases != null && purchases.size() > 0) {
            for (TopDto<Integer> purchase : purchases) {
                if (purchase.getObj().equals(StockConstant.SALE)) {
                    dataDto.setPurchases(BigDecimalUtil.formatTwoPoint(purchase.getSum()));
                }
                if (purchase.getObj().equals(StockConstant.BACK)) {
                    dataDto.setSalesBack(BigDecimalUtil.formatTwoPoint(purchase.getSum()));
                }
            }
        }
        return dataDto;
    }

    @Override
    public List<TrendDto> getPurchaseTrend(HomeInitParams params) {
        List<TrendDto> data = instockMapper.getPurchaseTrend(params);
        List<String> everyDate = TimeUtil.getEveryDate(params.getBeginTime(), params.getEndTime());
        if (everyDate == null) {
            return data;
        } else {
            List<TrendDto> result = new ArrayList<>();
            everyDate.forEach(e -> {
                TrendDto dto = new TrendDto();
                dto.setTime(e);
                dto.setSum(BigDecimalUtil.formatTwoPoint(new BigDecimal("0")));
                data.forEach(d -> {
                    if (e.equals(d.getTime())) {
                        dto.setSum(BigDecimalUtil.formatTwoPoint(d.getSum()));
                    }
                });
                result.add(dto);
            });
            return result;
        }
    }

    @Override
    public List<TopDto<String>> getTopSupplier(HomeInitParams params) {
        return instockMapper.getTopSupplier(params);
    }

    @Override
    public List<Instock> getInstockList(InstockPageParams params) {
        return instockMapper.getInstockList(params);
    }
}
